#include "Room.hh"
#include <iostream>
#include <algorithm>

namespace DungeonRPG {

Room::Room(const std::string& name, const std::string& description)
    : name(name), description(description) {}

Room::~Room() {
    // Clean up all items and enemies
    for (auto item : items) delete item;
    for (auto enemy : enemies) delete enemy;
    for (auto item : shopStock)
        if (item && item->ownedByRoom)
            delete item; // Only delete if owned by room
}

void Room::addItem(Item* item) {
    items.push_back(item);
}

void Room::addEnemy(Enemy* enemy) {
    if (!enemy) {
        std::cerr << "[Room::addEnemy] Null enemy pointer passed.\n";
        return;
    }

    const size_t maxEnemies = 5;
    if (enemies.size() >= maxEnemies) {
        std::cerr << "[Room::addEnemy] Enemy limit reached (" << maxEnemies << "). Cannot add more.\n";
        return;
    }
    for (Enemy* e : enemies) {
        if (e == enemy) {
            std::cerr << "[Room::addEnemy] Enemy already exists in room.\n";
            return;
        }
    }
    enemies.push_back(enemy);
    type = RoomType::Combat;
}


void Room::addConnection(const std::string& direction, Room* room) {
    // Connect this room to another in a direction
    connections[direction] = room;
}

Room* Room::getConnectedRoom(const std::string& direction) const {
    auto it = connections.find(direction);
    if (it != connections.end()) {
        return it->second;
    }
    return nullptr;
}

void Room::describe() const {
    // Display room name and description
    std::cout << "Room: " << name << "\n" << description << "\n";

    // List enemies if any
    if (!enemies.empty()) {
        std::cout << "Enemies:\n";
        for (auto e : enemies) {
            std::cout << " - " << e->getName() << ": " << e->getDescription() << "\n";
        }
    }

    // Special descriptions for shop or treasure
    if (type == RoomType::Shop) {
        std::cout << "This room is a shop. Type 'buy' to view and purchase goods.\n";
    } else if (type == RoomType::Treasure) {
        if (cleared) {
            std::cout << "This treasure room is empty.\n";
        } else {
            std::cout << "This room contains treasure. Type 'choose' to select a reward.\n";
        }
    }

    // Show items if room is cleared
    if (isCleared() && !items.empty()) {
        std::cout << "Items:\n";
        for (auto i : items) {
            std::cout << " - " << i->name << ": " << i->description << "\n";
        }
    }

    // List all connected directions
    if (!connections.empty()) {
        std::cout << "Exits: ";
        for (const auto& conn : connections) {
            std::cout << conn.first << " ";
        }
        std::cout << "\n";
    }
}

std::vector<Item*>& Room::getItems() {
    return items;
}

std::vector<Enemy*>& Room::getEnemies() {
    return enemies;
}

void Room::removeDeadEnemies() {
    // Remove and delete all dead enemies
    enemies.erase(
        std::remove_if(enemies.begin(), enemies.end(), [](Enemy* e) {
            if (!e->isAlive()) {
                delete e;
                return true;
            }
            return false;
        }),
        enemies.end());

    if (enemies.empty()) {
        cleared = true;
    }
}

void Room::markExplored() {
    explored = true;
}

bool Room::isExplored() const {
    return explored;
}

void Room::markCleared() {
    cleared = true;
}

bool Room::isCleared() const {
    return cleared;
}

void Room::setType(RoomType t) {
    type = t;
}

RoomType Room::getType() const {
    return type;
}

void Room::setShopStock(const std::vector<Item*>& stock) {
    shopStock = stock;

    // Prevent deletion of global static accessory objects
    for (auto* item : shopStock) {
        if (item == &LuckyCharm || item == &RustyRing ||
            item == &SharpTrinket || item == &HeavyPendant ||
            item == &VirtueBadge || item == &BloodCharm ||
            item == &OccultNecklace) {
            item->ownedByRoom = false;
        }
    }
}

const std::vector<Item*>& Room::getShopStock() const {
    return shopStock;
}

void Room::removeShopItem(int index) {
    // Remove item from shop and delete it
    if (index >= 0 && index < (int)shopStock.size()) {
        delete shopStock[index];
        shopStock.erase(shopStock.begin() + index);
    }
}

}
